﻿// Copyright (c) 2012 Mokah Nnamezie & Andrew Cooper
// Neo4Net graph database - http://neo4net.codeplex.com
//
// This file is part of Neo4Net - a .Net port of the Neo4j graph database
//
// Neo4Net is free software: you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
// the Free Software Foundation, either version 3 of the License, or
// (at your option) any later version.
//
// This program is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
// GNU General Public License for more details.
//
// You should have received a copy of the GNU General Public License
// along with this program.  If not, see <http://www.gnu.org/licenses/>.

namespace Neo4Net.Kernel.Impl.Cache
{
    using System;
    using NUnit.Framework;

    [TestFixture]
    public partial class TestLruCache
    {
        [Test]
        public void TestCreate()
        {
            Assert.That(() => new LruCache<object, object>("TestCache", 0), Throws.TypeOf<ArgumentOutOfRangeException>());

            LruCache<object, object> cache = new LruCache<object, object>("TestCache", 70);

            Assert.That(() => cache.Put(null, new object()), Throws.TypeOf<ArgumentNullException>());
            Assert.That(() => cache.Put(new object(), null), Throws.TypeOf<ArgumentNullException>());
            Assert.That(() => cache.Get(null), Throws.TypeOf<ArgumentNullException>());
            Assert.That(() => cache.Remove(null), Throws.TypeOf<ArgumentNullException>());

            cache.Put(new object(), new object());
            cache.Clear();
        }

        [Test]
        public void TestSimple()
        {
            LruCacheTest<object, object> cache = new LruCacheTest<object, object>("TestCache", 3);
            string s1 = "1";
            int key1 = 1;
            string s2 = "2";
            int key2 = 2;
            string s3 = "3";
            int key3 = 3;
            string s4 = "4";
            int key4 = 4;
            string s5 = "5";
            int key5 = 5;
            cache.Put(key1, s1);
            cache.Put(key2, s2);
            cache.Put(key3, s3);
            cache.Put(key2);
            Assert.That(cache.LastCleanedElement, Is.Null);
            cache.Put(key4, s4);
            Assert.That(cache.LastCleanedElement, Is.EqualTo(s1));
            cache.Put(key5, s5);
            Assert.That(cache.LastCleanedElement, Is.EqualTo(s3));
            int size = cache.Size;
            Assert.That(size, Is.EqualTo(3));
            Assert.That(cache.Get(key1), Is.Null);
            Assert.That(cache.Get(key2), Is.EqualTo(s2));
            Assert.That(cache.Get(key3), Is.Null);
            Assert.That(cache.Get(key4), Is.EqualTo(s4));
            Assert.That(cache.Get(key5), Is.EqualTo(s5));
            cache.Clear();
            Assert.That(cache.Size, Is.EqualTo(0));
        }

        [Test]
        public void TestResize()
        {
            LruCacheTest<object, object> cache = new LruCacheTest<object, object>("TestCache", 3);
            string s1 = "1";
            int key1 = 1;
            string s2 = "2";
            int key2 = 2;
            string s3 = "3";
            int key3 = 3;
            string s4 = "4";
            int key4 = 4;
            string s5 = "5";
            int key5 = 5;
            cache.Put(key1, s1);
            cache.Put(key2, s2);
            cache.Put(key3, s3);
            cache.Put(key2);
            Assert.That(cache.LastCleanedElement, Is.Null);
            Assert.That(cache.Size, Is.EqualTo(cache.MaxSize));
            cache.Resize(5);
            Assert.That(cache.MaxSize, Is.EqualTo(5));
            Assert.That(cache.Size, Is.EqualTo(3));
            cache.Put(key4, s4);
            Assert.That(cache.LastCleanedElement, Is.Null);
            cache.Put(key5, s5);
            Assert.That(cache.LastCleanedElement, Is.Null);
            Assert.That(cache.Size, Is.EqualTo(cache.MaxSize));
            cache.Resize(4);
            Assert.That(cache.LastCleanedElement, Is.EqualTo(s1));
            Assert.That(cache.Size, Is.EqualTo(cache.MaxSize));
            cache.Resize(3);
            Assert.That(cache.LastCleanedElement, Is.EqualTo(s3));
            Assert.That(cache.MaxSize, Is.EqualTo(3));
            Assert.That(cache.Size, Is.EqualTo(3));
        }
    }
}
